LVGL (6) 基础对象 Obj 分析

您所在的位置:网站首页 asserted state LVGL (6) 基础对象 Obj 分析

LVGL (6) 基础对象 Obj 分析

2023-10-24 17:37| 来源: 网络整理| 查看: 265

LVGL 中使用 lv_obj_t 来对常用的对象进行抽象:

typedef struct _lv_obj_t {     const lv_obj_class_t * class_p;     struct _lv_obj_t * parent;     _lv_obj_spec_attr_t * spec_attr;     _lv_obj_style_t * styles; #if LV_USE_USER_DATA     void * user_data; #endif     lv_area_t coords;     lv_obj_flag_t flags;     lv_state_t state;     uint16_t layout_inv : 1;     uint16_t scr_layout_inv : 1;     uint16_t skip_trans : 1;     uint16_t style_cnt  : 6;     uint16_t h_layout   : 1;     uint16_t w_layout   : 1; } lv_obj_t;

obj 结构作为 LVGL 内的一个基本抽象,包含了 area,style,parent 等内容;

以一个 button 为例,应用层代码创建一个 button 的代码;

创建对象 void LVGL_CentralButton(void) {     lv_obj_t *btn = lv_btn_create(lv_scr_act());     lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);     lv_obj_set_height(btn, 30);     lv_obj_t *label;     label = lv_label_create(btn);     lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);     lv_label_set_text(label, "LVGL");     static lv_style_t style_btn;     lv_style_init(&style_btn);     lv_style_set_radius(&style_btn, 10);     lv_style_set_border_color(&style_btn, lv_color_white());     lv_style_set_border_opa(&style_btn, LV_OPA_30);     lv_obj_add_style(btn, &style_btn, LV_STATE_DEFAULT); }

首先定义了一个 lv_obj_t *btn 的一个对象,然后调用 lv_btn_create 来创建一个 button;

#define MY_CLASS &lv_btn_class const lv_obj_class_t lv_btn_class  = {     .constructor_cb = lv_btn_constructor,     .width_def = LV_SIZE_CONTENT,     .height_def = LV_SIZE_CONTENT,     .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,     .instance_size = sizeof(lv_btn_t),     .base_class = &lv_obj_class }; lv_obj_t * lv_btn_create(lv_obj_t * parent) {     LV_LOG_INFO("begin");     lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);     lv_obj_class_init_obj(obj);     return obj; }

在每个组件中(比如 button、label)都定义了一个 MY_CLASS 的玩意,而且仅该文件使用,充分体现了 LVGL 将组件抽象为 class 的思想;

这个MY_CLASS 是一个 lv_obj_class_t 结构;

每一个 lv_obj_class_t 结构都包含了他的构造函数和析构函数,默认长宽等信息,如下所示:

typedef struct _lv_obj_class_t { const struct _lv_obj_class_t * base_class; void (*constructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj); void (*destructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj); #if LV_USE_USER_DATA void * user_data; #endif void (*event_cb)(const struct _lv_obj_class_t * class_p, struct _lv_event_t * e); /**< Widget type specific event function*/ lv_coord_t width_def; lv_coord_t height_def; uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/ uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/ uint32_t instance_size : 16; } lv_obj_class_t;

创建一个 button 的时候,首先调用 lv_obj_class_create_obj 函数,然后再调用 lv_obj_class_init_obj;

lv_btn_create |--> lv_obj_class_create_obj |--> lv_obj_class_init_obj

一个是创建 obj,另一个是初始化 obj;

来看一下 lv_obj_class_create_obj:

lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent) {     LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent);     uint32_t s = get_instance_size(class_p);     lv_obj_t * obj = lv_mem_alloc(s);     if(obj == NULL) return NULL;     lv_memset_00(obj, s);     obj->class_p = class_p;     obj->parent = parent;     /*Create a screen*/     if(parent == NULL) {         LV_TRACE_OBJ_CREATE("creating a screen");         lv_disp_t * disp = lv_disp_get_default();         if(!disp) {             LV_LOG_WARN("No display created yet. No place to assign the new screen");             return NULL;         }         if(disp->screens == NULL) {             disp->screens = lv_mem_alloc(sizeof(lv_obj_t *));             disp->screens[0] = obj;             disp->screen_cnt = 1;         }         else {             disp->screen_cnt++;             disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt);             disp->screens[disp->screen_cnt - 1] = obj;         }         /*Set coordinates to full screen size*/         obj->coords.x1 = 0;         obj->coords.y1 = 0;         obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1;         obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1;     }     /*Create a normal object*/     else {         LV_TRACE_OBJ_CREATE("creating normal object");         LV_ASSERT_OBJ(parent, MY_CLASS);         if(parent->spec_attr == NULL) {             lv_obj_allocate_spec_attr(parent);         }         if(parent->spec_attr->children == NULL) {             parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *));             parent->spec_attr->children[0] = obj;             parent->spec_attr->child_cnt = 1;         }         else {             parent->spec_attr->child_cnt++;             parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,                                                          sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);             parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;         }     }     return obj; }

主要就是创建了 obj 对象;

下面调用 lv_obj_class_init_obj 对 obj 进行初始化:

void lv_obj_class_init_obj(lv_obj_t * obj) { // 标记 screen 为 dirty (设置 scr->scr_layout_inv = 1),在更新 layout 的时候会用到;     lv_obj_mark_layout_as_dirty(obj); // 禁止 style 刷新     lv_obj_enable_style_refresh(false);     lv_theme_apply(obj); // 调用对应组件的构造函数;     lv_obj_construct(obj); // 使能 style 刷新     lv_obj_enable_style_refresh(true);     lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);     lv_obj_refresh_self_size(obj);     lv_group_t * def_group = lv_group_get_default();     if(def_group && lv_obj_is_group_def(obj)) {         lv_group_add_obj(def_group, obj);     }     lv_obj_t * parent = lv_obj_get_parent(obj);     if(parent) {         /*Call the ancestor's event handler to the parent to notify it about the new child.          *Also triggers layout update*/         lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);         lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj);         /*Invalidate the area if not screen created*/ // 标记为 obj 无效,即需要被更新         lv_obj_invalidate(obj);     } }

屏幕,是没有父类的基础对象;

小结

所以,可以看到,通过如下方式进行创建 button 的时候 (打个比方)

    lv_obj_t *btn = lv_btn_create(lv_scr_act());     lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);     lv_obj_set_height(btn, 30);

那么这个 button 的 parent 就会被指定为当前的 scr_act 屏幕;



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3